package org.example.listener;

import cn.hutool.core.bean.BeanUtil;
import org.example.component.LoginInfo;
import org.example.component.UserInfo;
import org.example.config.Chat;
import org.example.config.ImConfig;
import org.example.config.ImSessionContext;
import org.example.enums.KeyEnum;
import org.example.enums.RoomRoleEnum;
import org.example.packets.ImClientNode;
import org.example.packets.Status;
import org.example.packets.bean.Group;
import org.example.packets.bean.User;
import org.example.packets.handler.user.GroupUser;
import org.example.packets.handler.user.UserStatusBody;
import org.example.service.UserGroupService;
import org.example.service.UserService;
import org.example.util.ChannelContextUtil;
import org.tio.core.ChannelContext;
import org.tio.core.Node;
import org.tio.core.intf.Packet;
import org.tio.websocket.server.WsTioServerListener;

import java.util.List;

import static org.example.component.AbstractStorage.setValue;

public class ImTioServerListener extends WsTioServerListener {

    private final UserService userService = new UserService();

    private final UserGroupService userGroupService = new UserGroupService();

    public static final ImTioServerListener me = new ImTioServerListener();

    @Override
    public boolean onHeartbeatTimeout(ChannelContext channelContext, Long interval, int heartbeatTimeoutCount) {
        return false;
    }

    @Override
    public void onAfterConnected(ChannelContext channelContext, boolean isConnected, boolean isReconnect) throws Exception {
        ImSessionContext sessionContext = new ImSessionContext();
        Node clientNode = channelContext.getClientNode();
        ImClientNode build = ImClientNode.builder().ip(clientNode.getIp()).port(clientNode.getPort()).build();
        build.setId(channelContext.getId());
        sessionContext.setImClientNode(build);
        channelContext.set(KeyEnum.IM_CHANNEL_SESSION_CONTEXT_KEY.getKey(), sessionContext);
        super.onAfterConnected(channelContext, isConnected, isReconnect);
    }

    @Override
    public void onAfterDecoded(ChannelContext channelContext, Packet packet, int packetSize) throws Exception {
        // 设置线程上下文
//        System.out.println("设置线程上下文");
        LoginInfo loginInfo = new LoginInfo().setChannelContext(channelContext);
        setValue(loginInfo);
        super.onAfterDecoded(channelContext, packet, packetSize);
    }

    @Override
    public void onAfterReceivedBytes(ChannelContext channelContext, int receivedBytes) throws Exception {
        super.onAfterReceivedBytes(channelContext, receivedBytes);
    }

    @Override
    public void onAfterSent(ChannelContext channelContext, Packet packet, boolean isSentSuccess) throws Exception {
        super.onAfterSent(channelContext, packet, isSentSuccess);
    }

    @Override
    public void onAfterHandled(ChannelContext channelContext, Packet packet, long cost) throws Exception {
        super.onAfterHandled(channelContext, packet, cost);
    }

    @Override
    public void onBeforeClose(ChannelContext channelContext, Throwable throwable, String remark, boolean isRemove) throws Exception {
        setValue(new LoginInfo().setChannelContext(channelContext));

        User user = UserInfo.user();
        List<ChannelContext> channelContexts = ChannelContextUtil.contextList(user.getId());
        // 首先判断能不能拿到用户
        // 然后判断是不是多机器登录, 当仅在当前登录时, 更新用户状态为离线
        if (channelContexts.size() > 1) {
            super.onBeforeClose(channelContext, throwable, remark, isRemove);
            return;
        }

        // 回调用户状态变化
        ImConfig.get().getImUserPropListener().onStatusChange(Status.offline());

        user.setStatus(Status.offline());
        UserStatusBody build = UserStatusBody.builder().user(BeanUtil.copyProperties(user, GroupUser.class)).build();

        for (Group group : UserInfo.groups()) {
            GroupUser userGroup = group.getUsers().stream().filter(x -> x.getId().equals(user.getId())).findFirst().orElse(null);
            build.getUser().setRole(null == userGroup ? RoomRoleEnum.GENERAL : userGroup.getRole());
            build.setRoomId(group.getRoomId());

            Chat.sendToGroup(build, channelContext);
        }

        super.onBeforeClose(channelContext, throwable, remark, isRemove);
    }
}
